﻿using System;
using System.Configuration;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Web;
using System.Web.UI;

namespace Common
{
    public class AnnexUploadUtil : Page
    {
        private readonly string _basePath = ConfigurationManager.AppSettings["ImageBasePath"];

        #region ImageUpload[上传图片并缩减尺寸，保存原图]

        /// <summary>
        /// 上传图片并缩减尺寸，保存原图
        /// </summary>
        /// <param name="narrowPath">缩小的图片路径</param>
        /// <param name="originalPath">原始图片路径</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="file">上传文件访问对象</param>
        /// <param name="package">保存文件夹，可为null</param>
        /// <param name="fileName">保存文件名，可为null</param>
        /// <param name="dbl">是否等比例缩放</param>
        /// <returns></returns>
        public AnnexDto ImageUpload(String narrowPath, String originalPath, int width, int height,
                                    HttpPostedFileBase file, string package, string fileName, bool dbl)
        {
            int errState;
            return ImageUpload(narrowPath, originalPath, width, height, 0, 0, file, package, fileName, dbl, out errState);
        }

        #endregion

        /// <summary>
        /// 需要的算法在这里写
        /// </summary>
        /// <param name="narrowPath"></param>
        /// <param name="originalPath"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="limitWidth"></param>
        /// <param name="limitHeight"></param>
        /// <param name="file"></param>
        /// <param name="package"></param>
        /// <param name="fileName"></param>
        /// <param name="dbl"></param>
        /// <param name="errorState">错误状态（0-正确，1-异常，2-高度错误，3-宽度错误）</param>
        /// <returns></returns>
        public AnnexDto ImageUpload(String narrowPath, String originalPath, int width, int height, int limitWidth,
                                    int limitHeight, HttpPostedFileBase file, string package, string fileName, bool dbl,
                                    out int errorState)
        {
            errorState = 0;
            Bitmap newImage = null;
            Image oldImage = null;
            try
            {
                string sfileName = file.FileName;
                package = package ?? DateTime.Now.ToString("yyyy-MM-dd");
                fileName = fileName ?? DateTime.Now.ToString("hhmmss") + "_" + Guid.NewGuid();
                AnnexDto annexModel = null;

                //创建原图片保存位置
                CheckUpDirectory(_basePath + originalPath + "/" + package);
                string extensionName = Path.GetExtension(file.FileName);
                if (extensionName != String.Empty)
                {
                    file.SaveAs(_basePath + originalPath + "/" + package + "/" + fileName + extensionName);

                    //原图
                    oldImage = Image.FromFile(_basePath + originalPath + "/" + package + "/" + fileName + extensionName);
                    if (limitHeight != 0 && limitHeight != oldImage.Height)
                    {
                        errorState = 2;
                        File.Delete(_basePath + originalPath + "/" + package + "/" + fileName + extensionName);
                        return null;
                    }
                    else if (limitWidth != 0 && limitWidth != oldImage.Width)
                    {
                        errorState = 3;
                        File.Delete(_basePath + originalPath + "/" + package + "/" + fileName + extensionName);
                        return null;
                    }
                    //等比缩放
                    if (dbl) //等比缩放相当于把原图缩小然后放在一个特定尺寸的相框中
                    {
                        if (oldImage.Width > width) //如果原图的宽大于相框的宽度,先把原图的宽设为相框的宽
                        {
                            double tempHeight = (double) width*oldImage.Height/oldImage.Width; //然后高度按等比公式可算出来
                            if (tempHeight > height) //如果新的高度比相框的高度大,那就要把原图的高度设为相框的高度,宽度要进一步缩小
                            {
                                width = height*oldImage.Width/oldImage.Height;
                            }
                            else //如果新的高度比相框的高度小或相等,那新的高度就直接取第一次缩放后得到的新高度
                            {
                                height = (int) tempHeight;
                            }
                        }
                        else if (oldImage.Height > height)
                        {
                            double tempWidth = (double) oldImage.Width*height/oldImage.Height;
                            if (tempWidth > width)
                            {
                                height = oldImage.Height*width/oldImage.Width;
                            }
                            else
                            {
                                width = oldImage.Width*height/oldImage.Height;
                            }
                        }
                    }
                    //缩图
                    newImage = new Bitmap(width, height);
                    newImage.SetResolution(oldImage.HorizontalResolution, oldImage.VerticalResolution);
                    Graphics graphics = Graphics.FromImage(newImage);
                    graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    graphics.DrawImage(oldImage, new Rectangle(0, 0, width, height), 0, 0, oldImage.Width,
                                       oldImage.Height, GraphicsUnit.Pixel);

                    //创建用于保存缩好的图片的文件夹
                    CheckUpDirectory(_basePath + narrowPath + "/" + package);

                    //把缩好的图片保存，释放资源
                    newImage.Save(_basePath + narrowPath + "/" + package + "/" + fileName + extensionName,
                                  ImageFormat.Jpeg);

                    //返回上传文件内容
                    annexModel = new AnnexDto
                                     {
                                         AnnexName = sfileName,
                                         AnnexOriginalPath =
                                             originalPath + "/" + package + "/" + fileName + extensionName,
                                         AnnexNarrowPath = narrowPath + "/" + package + "/" + fileName + extensionName,
                                         AnnexSize = file.ContentLength,
                                         AnnexHeight = height,
                                         AnnexWidth = width,
                                         AnnexDate = DateTime.Now,
                                         AnnexDomain = _basePath
                                     };
                }
                return annexModel;
            }
            catch (Exception ex)
            {
                errorState = 1;
                Log.LogHandler.LogError(
                    "ImageUpload(String sPath, String bPath, int width, int height, HttpPostedFile file, string package, string fileName)",
                    ex);
                return null;
            }
            finally
            {
                if (newImage != null) newImage.Dispose();
                if (oldImage != null) oldImage.Dispose();
            }
        }

        public AnnexDto TempImageUpload(String path, HttpPostedFileBase file, string package, string fileName)
        {
            Image oldImage = null;
            try
            {
                string sfileName = file.FileName;
                package = package ?? DateTime.Now.ToString("yyyy-MM-dd");
                fileName = fileName ?? DateTime.Now.ToString("hhmmss") + "_" + Guid.NewGuid();
                AnnexDto annexModel = null;
                //创建原图片保存位置
                CheckUpDirectory(Server.MapPath(path + "/" + package));
                //获取扩展名
                string extensionName = Path.GetExtension(file.FileName);
                if (extensionName != String.Empty)
                {
                    file.SaveAs(Server.MapPath(path + "/" + package + "/" + fileName + extensionName));
                    oldImage = Image.FromFile(Server.MapPath(path + "/" + package + "/" + fileName + extensionName));
                    //返回上传文件内容
                    annexModel = new AnnexDto
                                     {
                                         AnnexName = sfileName,
                                         AnnexOriginalPath = path + "/" + package + "/" + fileName + extensionName,
                                         AnnexNarrowPath = path + "/" + package + "/" + fileName + extensionName,
                                         AnnexSize = file.ContentLength,
                                         AnnexHeight = oldImage.Height,
                                         AnnexWidth = oldImage.Width,
                                         AnnexDate = DateTime.Now,
                                         AnnexDomain = _basePath
                                     };
                    oldImage.Dispose();
                }
                return annexModel;
            }
            catch (Exception ex)
            {
                Log.LogHandler.LogError(
                    "ImageUpload(String path, HttpPostedFileBase file, string package, string fileName)", ex);
                return null;
            }
            finally
            {
                if (oldImage != null)
                {
                    oldImage.Dispose();
                }
            }
        }

        public AnnexDto ImageUpload(String path, HttpPostedFileBase file, string package, string fileName)
        {
            int errorState;
            return ImageUpload(path, file, package, fileName, 0, 0, out errorState);
        }

        public AnnexDto ImageUpload(String path, HttpPostedFileBase file, string package, string fileName,
                                    int limitWidth, int limitHeight, out int errorState)
        {
            errorState = 0;
            Image oldImage = null;
            try
            {
                string sfileName = file.FileName;
                package = string.IsNullOrEmpty(package) ? DateTime.Now.ToString("yyyy-MM-dd") : package;
                fileName = string.IsNullOrEmpty(fileName)
                               ? DateTime.Now.ToString("hhmmss") + "_" + Guid.NewGuid()
                               : fileName;
                AnnexDto annexModel = null;
                //创建原图片保存位置
                CheckUpDirectory(_basePath + path + "/" + package);
                //获取扩展名
                string extensionName = Path.GetExtension(file.FileName);
                if (extensionName != String.Empty)
                {
                    file.SaveAs(_basePath + path + "/" + package + "/" + fileName + extensionName);
                    oldImage = Image.FromFile(_basePath + path + "/" + package + "/" + fileName + extensionName);
                    if (limitHeight != 0 && limitHeight != oldImage.Height)
                    {
                        errorState = 2;
                        oldImage.Dispose();
                        File.Delete(_basePath + path + "/" + package + "/" + fileName + extensionName);
                        return null;
                    }
                    else if (limitWidth != 0 && limitWidth != oldImage.Width)
                    {
                        errorState = 3;
                        oldImage.Dispose();
                        File.Delete(_basePath + path + "/" + package + "/" + fileName + extensionName);
                        return null;
                    }
                    //返回上传文件内容
                    annexModel = new AnnexDto
                                     {
                                         AnnexName = sfileName,
                                         AnnexOriginalPath = path + "/" + package + "/" + fileName + extensionName,
                                         AnnexNarrowPath = path + "/" + package + "/" + fileName + extensionName,
                                         AnnexSize = file.ContentLength,
                                         AnnexHeight = oldImage.Height,
                                         AnnexWidth = oldImage.Width,
                                         AnnexDate = DateTime.Now,
                                         AnnexDomain = _basePath
                                     };
                    oldImage.Dispose();
                }
                return annexModel;
            }
            catch (Exception ex)
            {
                errorState = 1;
                Log.LogHandler.LogError(
                    "ImageUpload(String path, HttpPostedFileBase file, string package, string fileName)", ex);
                return null;
            }
            finally
            {
                if (oldImage != null)
                {
                    oldImage.Dispose();
                }
            }
        }

        /// <summary>
        /// 从源图中截取一小块图片
        /// </summary>
        /// <param name="sFromFilePath">原图</param>
        /// <param name="saveFilePath">保存路径</param>
        /// <param name="width">截取的图宽</param>
        /// <param name="height">截取的图高</param>
        /// <param name="startX">开始的X坐标</param>
        /// <param name="startY">开始的Y坐标</param>
        public AnnexDto CaptureImage(string sFromFilePath, string saveFilePath, int width, int height, int startX,
                                     int startY)
        {
            string package = DateTime.Now.ToString("yyyy-MM-dd");
            string fileName = DateTime.Now.ToString("hhmmss") + "_" + Guid.NewGuid();

            //载入底图
            Image fromImage = Image.FromFile(Server.MapPath("~" + sFromFilePath));
            //创建新图位图
            var bitmap = new Bitmap(width, height);
            //创建作图区域
            Graphics graphic = Graphics.FromImage(bitmap);
            //截取原图相应区域写入作图区
            graphic.DrawImage(fromImage, 0, 0, new Rectangle(startX, startY, width, height), GraphicsUnit.Pixel);
            //从作图区生成新图
            Image saveImage = Image.FromHbitmap(bitmap.GetHbitmap());
            //创建原图片保存位置
            CheckUpDirectory(_basePath + saveFilePath + "/" + package);
            //保存图象
            saveFilePath = saveFilePath + "/" + package + "/" + fileName + ".jpg";
            saveImage.Save(_basePath + saveFilePath, ImageFormat.Jpeg);

            //返回上传文件内容
            var fs = new FileStream(_basePath + saveFilePath, FileMode.Open, FileAccess.Read);
            var annexModel = new AnnexDto
                                 {
                                     AnnexName = fileName,
                                     AnnexOriginalPath = saveFilePath,
                                     AnnexNarrowPath = "",
                                     AnnexSize = (int) fs.Length,
                                     AnnexHeight = saveImage.Height,
                                     AnnexWidth = saveImage.Width,
                                     AnnexDate = DateTime.Now,
                                     AnnexDomain = _basePath
                                 };

            //释放资源
            saveImage.Dispose();
            bitmap.Dispose();
            graphic.Dispose();

            return annexModel;
        }

        /// <summary>
        /// 从临时图片区保存图片
        /// </summary>
        /// <param name="sFromFilePath">原图</param>
        /// <param name="imageName">图片原名</param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="sPath"></param>
        /// <param name="bPath"></param>
        /// <param name="dbl"></param>
        /// <returns></returns>
        public AnnexDto ImageUpload(string sFromFilePath, string imageName, int width, int height, String sPath,
                                    String bPath, bool dbl)
        {
            string package = DateTime.Now.ToString("yyyy-MM-dd");
            string fileName = DateTime.Now.ToString("hhmmss") + "_" + Guid.NewGuid();
            string saveNarrowPath = _basePath + sPath + "/" + package;
            string saveOriginalPath = _basePath + bPath + "/" + package;
            //载入底图
            Image fromImage = Image.FromFile(Server.MapPath("~" + sFromFilePath));
            //创建原图片保存位置
            CheckUpDirectory(saveOriginalPath);
            //保存原图
            File.Copy(Server.MapPath("~" + sFromFilePath), saveOriginalPath + "/" + fileName + ".jpg");
            if (dbl)
            {
                double rate = (double) fromImage.Width/width;
                double s = (double) fromImage.Height/height;
                if (s > rate)
                {
                    rate = s;
                }
                double w = fromImage.Width/rate;
                double h = fromImage.Height/rate;

                width = (int) Math.Round(w, MidpointRounding.AwayFromZero);
                height = (int) Math.Round(h, MidpointRounding.AwayFromZero);
            }
            var newImage = new Bitmap(width, height);
            newImage.SetResolution(fromImage.HorizontalResolution, fromImage.VerticalResolution);
            Graphics graphics = Graphics.FromImage(newImage);
            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            graphics.DrawImage(fromImage, new Rectangle(0, 0, width, height), 0, 0, fromImage.Width, fromImage.Height,
                               GraphicsUnit.Pixel);
            //创建用于保存缩好的图片的文件夹
            CheckUpDirectory(saveNarrowPath);

            //把缩好的图片保存，释放资源
            const string extensionName = ".jpg";
            newImage.Save(saveNarrowPath + "/" + fileName + extensionName, ImageFormat.Jpeg);

            //返回上传文件内容
            var fs = new FileStream(Server.MapPath(sFromFilePath), FileMode.Open, FileAccess.Read);
            var annexModel = new AnnexDto
                                 {
                                     AnnexName = imageName,
                                     AnnexOriginalPath = bPath + "/" + package + "/" + fileName + extensionName,
                                     AnnexNarrowPath = sPath + "/" + package + "/" + fileName + extensionName,
                                     AnnexSize = (int) fs.Length,
                                     AnnexHeight = height,
                                     AnnexWidth = width,
                                     AnnexDate = DateTime.Now,
                                     AnnexDomain = _basePath
                                 };

            return annexModel;
        }

        #region CheckUpDirectory[判断路径是否存在，不存在则创建]

        /// <summary>
        /// 判断路径是否存在，不存在则创建
        /// </summary>
        /// <param name="uploadDirectory"></param>
        private static void CheckUpDirectory(String uploadDirectory)
        {
            if (Directory.Exists(uploadDirectory))
            {
                return;
            }

            Directory.CreateDirectory(uploadDirectory);
        }

        #endregion

        #region TempImageUpload[上传图片并缩减尺寸，保存原图]

        /// <summary>
        /// 上传图片并缩减尺寸，保存原图
        /// </summary>
        /// <param name="narrowPath">缩小的图片路径</param>
        /// <param name="originalPath">原始图片路径</param>
        /// <param name="width">宽度</param>
        /// <param name="height">高度</param>
        /// <param name="file">上传文件访问对象</param>
        /// <param name="package">保存文件夹，可为null</param>
        /// <param name="fileName">保存文件名，可为null</param>
        /// <param name="dbl">是否等比例缩放</param>
        /// <returns></returns>
        public AnnexDto TempImageUpload(String narrowPath, String originalPath, int width, int height,
                                        HttpPostedFileBase file, string package, string fileName, bool dbl)
        {
            Bitmap newImage = null;
            Image oldImage = null;
            try
            {
                string sfileName = file.FileName;
                package = package ?? DateTime.Now.ToString("yyyy-MM-dd");
                fileName = fileName ?? DateTime.Now.ToString("hhmmss") + "_" + Guid.NewGuid();
                AnnexDto annexModel = null;
                //创建原图片保存位置
                CheckUpDirectory(Server.MapPath(originalPath + "/" + package));
                string extensionName = Path.GetExtension(file.FileName);
                if (extensionName != String.Empty)
                {
                    file.SaveAs(Server.MapPath(originalPath + "/" + package + "/" + fileName + extensionName));

                    //缩图
                    oldImage =
                        Image.FromFile(Server.MapPath(originalPath + "/" + package + "/" + fileName + extensionName));
                    if (dbl)
                    {
                        double rate = 0d, s = 0d;
                        if (oldImage.Width > width)
                        {
                            rate = (double) oldImage.Width/width;
                        }
                        if (oldImage.Height > height)
                        {
                            s = (double) oldImage.Height/height;
                        }
                        if (s > rate)
                        {
                            rate = s;
                        }
                        if (s != 0d)
                        {
                            double w = oldImage.Width/rate;
                            double h = oldImage.Height/rate;

                            width = (int) Math.Round(w, MidpointRounding.AwayFromZero);
                            height = (int) Math.Round(h, MidpointRounding.AwayFromZero);
                        }
                        else
                        {
                            width = oldImage.Width;
                            height = oldImage.Height;
                        }
                    }
                    newImage = new Bitmap(width, height);
                    newImage.SetResolution(oldImage.HorizontalResolution, oldImage.VerticalResolution);
                    Graphics graphics = Graphics.FromImage(newImage);
                    graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    graphics.DrawImage(oldImage, new Rectangle(0, 0, width, height), 0, 0, oldImage.Width,
                                       oldImage.Height, GraphicsUnit.Pixel);

                    //创建用于保存缩好的图片的文件夹
                    CheckUpDirectory(Server.MapPath(narrowPath + "/" + package));

                    //把缩好的图片保存，释放资源
                    newImage.Save(Server.MapPath(narrowPath + "/" + package + "/" + fileName + extensionName),
                                  ImageFormat.Jpeg);

                    //返回上传文件内容
                    annexModel = new AnnexDto
                                     {
                                         AnnexName = sfileName,
                                         AnnexOriginalPath =
                                             originalPath + "/" + package + "/" + fileName + extensionName,
                                         AnnexNarrowPath = narrowPath + "/" + package + "/" + fileName + extensionName,
                                         AnnexSize = file.ContentLength,
                                         AnnexHeight = height,
                                         AnnexWidth = width,
                                         AnnexDate = DateTime.Now,
                                         AnnexDomain = _basePath
                                     };
                }
                return annexModel;
            }
            catch (Exception ex)
            {
                Log.LogHandler.LogError(
                    "ImageUpload(String sPath, String bPath, int width, int height, HttpPostedFile file, string package, string fileName)",
                    ex);
                return null;
            }
            finally
            {
                if (newImage != null) newImage.Dispose();
                if (oldImage != null) oldImage.Dispose();
            }
        }

        #endregion
    }
}